﻿using System;
using System.Collections.Generic;
using System.Net.Sockets;
using UnityEngine;

namespace PokerGame
{
    /// <summary>
    /// 客户端Socket的封装
    /// </summary>
    public class ClientPeer
    {
        private readonly Socket _socket;
        private readonly string _ip;
        private readonly int _port;

        public ClientPeer(string ip, int port)
        {
            try
            {
                _socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                _ip = ip;
                _port = port;
            }
            catch (Exception e)
            {
                Debug.LogError(e.Message);
            }
        }
        public void Connect()
        {
            try
            {
                _socket.Connect(_ip, _port);
                Debug.Log("服务器连接成功!");
                StartReceive();
            }
            catch (Exception e)
            {
                Debug.LogError(e.Message);
            }
        }
        #region receive
        // 接收数据缓冲区
        private byte[] receiveBuffer = new byte[1024];
        // 将接收数据装入List容器方便处理
        private List<byte> dataCache = new();
        private bool isProcessReceive = false;
        //SocketMessage缓冲队列
        public Queue<SocketMessage> MessageQueue { get; } = new();

        /// <summary>
        /// 开始异步接收数据
        /// </summary>
        private void StartReceive()
        {
            if (_socket == null || _socket.Connected == false)
            {
                Debug.LogError("服务器连接失败，无法发送数据...");
                return;
            }
            _socket.BeginReceive(receiveBuffer, 0, 1024, SocketFlags.None, ReceiveCallBack, _socket);
        }

        private void ReceiveCallBack(IAsyncResult result)
        {
            try
            {
                int length = _socket.EndReceive(result);
                byte[] buffer = new byte[length];
                Buffer.BlockCopy(receiveBuffer, 0, buffer, 0, length);
                //处理接收到的数据
                dataCache.AddRange(buffer);
                if (isProcessReceive == false)
                {
                    ProcessReceive();
                }
                StartReceive();
            }
            catch (Exception e)
            {
                Debug.LogError(e.Message);
            }
        }

        /// <summary>
        /// 处理接收数据
        /// </summary>
        private void ProcessReceive()
        {
            isProcessReceive = true;
            //解析数据包
            byte[] data = EncodeTool.DecodePacket(ref dataCache);

            if (data == null)
            {
                isProcessReceive = false;
                return;
            }
            SocketMessage message = EncodeTool.DecodeMessage(data);    
            MessageQueue.Enqueue(message);

            ProcessReceive();
        }
        #endregion

        #region send
        public void Send(int opCode, int subCode, object value)
        {
            SocketMessage message = new(opCode, subCode, value);
            Send(message);
        }
        public void Send(SocketMessage message)
        {
            byte[] data = EncodeTool.EncodeMessage(message);
            byte[] packet = EncodeTool.EncodePacket(data);
            try
            {
                _socket.Send(packet);
            }
            catch (Exception e)
            {
                Debug.LogError(e.Message);
            }
        }
        #endregion
    }
}
